package com.manager.common.ssh;

import com.jcraft.jsch.*;
import com.manager.common.utils.DataTools;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

@SuppressWarnings("all")
public class RemoteExecuteLinuxCommandTools {

	/****
	 * 
	 * 只支持linux
	 * 
	 ***/
	public static boolean uploadFileBySFTP(String remoteDirPath, String remoteFilName, String localFilePath,List<String> out){
		String ip = DataTools.getSystemSettingStringValByKey("linux.server.sftp.ip");
		int port = DataTools.getSystemSettingIntValByKey("linux.server.sftp.port");
		String userName = DataTools.getSystemSettingStringValByKey("linux.server.sftp.user.name");
		String password =  DataTools.getSystemSettingStringValByKey("linux.server.sftp.password");
		return uploadFileBySFTP(ip,userName,password,port,remoteDirPath,remoteFilName,localFilePath,out);
	}

	public static List<ChannelSftp.LsEntry> getRemoteLsEntryByDir(String remoteDirPath){
		String ip = DataTools.getSystemSettingStringValByKey("linux.server.sftp.ip");
		int port = DataTools.getSystemSettingIntValByKey("linux.server.sftp.port");
		String userName = DataTools.getSystemSettingStringValByKey("linux.server.sftp.user.name");
		String password =  DataTools.getSystemSettingStringValByKey("linux.server.sftp.password");

		Session session = null;
		Channel channel = null;
		ChannelSftp channelSftp = null;
		List<ChannelSftp.LsEntry> lsEntries = new ArrayList<>();
		try {
			JSch jsch = new JSch();
			session = jsch.getSession(userName, ip, 22); // 默认端口是22
			session.setPassword(password);
			session.setConfig("StrictHostKeyChecking", "no"); // 首次连接时忽略密钥检查
			session.connect();

			channel = session.openChannel("sftp");
			channel.connect();
			channelSftp = (ChannelSftp) channel;

			// 获取指定目录下的文件列表
			Vector<?> fileList = channelSftp.ls(remoteDirPath);
			for (Object fileObj : fileList) {
				ChannelSftp.LsEntry entry = (ChannelSftp.LsEntry) fileObj;
				lsEntries.add(entry);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (channelSftp != null) {
				channelSftp.exit();
			}
			if (channel != null) {
				channel.disconnect();
			}
			if (session != null) {
				session.disconnect();
			}
		}
		return lsEntries;
	}

	public static boolean downloadFileBySftp(String remoteFilePath, String localFilePath,List<String> out){
		String ip = DataTools.getSystemSettingStringValByKey("linux.server.sftp.ip");
		int port = DataTools.getSystemSettingIntValByKey("linux.server.sftp.port");
		String userName = DataTools.getSystemSettingStringValByKey("linux.server.sftp.user.name");
		String password =  DataTools.getSystemSettingStringValByKey("linux.server.sftp.password");
		return downloadFileBySftp(ip,userName,password,port,remoteFilePath,localFilePath,out);
	}

	public static boolean downloadFileBySftp(String ip, String userName, String password, int port,
											 String remoteFilePath, String localFilePath,List<String> out){
		SftpClient sftpClient = null;
		try{
			sftpClient = new SftpClient(ip,userName,password,port);
			ChannelSftp channelSftp = sftpClient.getChannelSftp();
			File file = new File(localFilePath);
			if(!file.exists()){
				file.getParentFile().mkdirs();
			}
			channelSftp.get(remoteFilePath,file.getParentFile().getAbsolutePath());
			remoteFilePath = remoteFilePath.replaceAll("\\\\","/");
			String fileName = remoteFilePath.substring(remoteFilePath.lastIndexOf("/")+1,remoteFilePath.length());
			new File(file.getParentFile().getAbsolutePath() + "/" + fileName).renameTo(file);
			return true;
		}catch (Exception e){
			e.printStackTrace();
		}finally {
			if(sftpClient != null){
				sftpClient.close();
			}
		}
		return false;
	}

	public static boolean uploadFileBySFTP(String ip, String userName, String password, int port,
			String remoteDirPath, String remoteFilName, String localFilePath,List<String> out)  {
		SftpClient sftpClient = null;
		try{

			sftpClient = new SftpClient(ip,userName,password,port);
			ChannelSftp sftp =  sftpClient.getChannelSftp();
			mkdir(remoteDirPath, sftp);

			sftp.put(localFilePath, remoteDirPath + "/" + remoteFilName);

			return true;
			
		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			out.add(e.getMessage());
		}finally {
			if(sftpClient != null){
				sftpClient.close();
			}
		}
		
		return false;
	}
	
	
	private static void mkdir(String remoteDirPath,ChannelSftp sftp) throws SftpException{
		String[] arr = remoteDirPath.split("/");
		String temp = "/";
		for(String path:arr){
			if(StringUtils.isEmpty(path)){
				continue;
			}
			temp += path + "/";
			try {
				sftp.lstat(temp).isDir();
			} catch (Exception e) {
				// TODO: handle exception
				sftp.mkdir(temp);
				sftp.cd(temp);
			}
		}
	}
	
	
	/***
	 *
	 * 远程批量执行linux命令
	 *
	 **/
	public static boolean excuteRemoteSSH(String ip, String userName, String password, int port,
			List<String> out,String... commands) {

		JSch jsch = new JSch();
		Session session = null;
		
		try{
			session = jsch.getSession(userName, ip, port);
			session.setPassword(password);

			Properties sshConfig = new Properties();
			sshConfig.put("StrictHostKeyChecking", "no");

			session.setConfig(sshConfig);

			session.connect(60 * 1000);

			String buffer;
			InputStreamReader isr = null;
			BufferedReader reader = null;

			for (String command : commands) {
				Channel channel = session.openChannel("exec");
				ChannelExec channelExec = (ChannelExec) channel;

				channelExec.setCommand(command);
				channel.setInputStream(null);
				channelExec.setErrStream(System.err);
				channel.connect();

				InputStream in = channelExec.getInputStream();
				isr = new InputStreamReader(in, StandardCharsets.UTF_8);
				reader = new BufferedReader(isr);

				while ((buffer = reader.readLine()) != null) {
					out.add(buffer);
				}

				isr.close();
				reader.close();
				
				channelExec.disconnect();

				channel.disconnect();

			}
			
			return true;
			
		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			out.add(e.getMessage());
		}finally {
			if(session != null){
				session.disconnect();
			}
		}
		
		return false;
	}

	public static boolean excuteRemoteSSH(Session session,
										  List<String> out,String... commands) {


		try{
			String buffer;
			InputStreamReader isr = null;
			BufferedReader reader = null;

			for (String command : commands) {

				out.add(command);
				Channel channel = session.openChannel("exec");
				ChannelExec channelExec = (ChannelExec) channel;

				channelExec.setCommand(command);
				channel.setInputStream(null);
				channelExec.setErrStream(System.err);
				channel.connect();

				InputStream in = channelExec.getInputStream();
				isr = new InputStreamReader(in, StandardCharsets.UTF_8);
				reader = new BufferedReader(isr);

				while ((buffer = reader.readLine()) != null) {
					out.add(buffer);
				}

				isr.close();
				reader.close();

				channelExec.disconnect();

				channel.disconnect();

			}

			return true;

		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			out.add(e.getMessage());
		}finally {
		}

		return false;
	}
	public static boolean isActive(String ip, String userName, String password, int port,String serviceName,List<String> out) {
		
		try{
			excuteRemoteSSH(ip, userName, password, port, out,new String[]{"systemctl status "+serviceName});
			for(String line:out){
				if(line.contains("Active")){
					String[] arr = line.split(":");
					if(arr[1].trim().startsWith("active")){
						return true;
					}
				}
			}
		}catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		return false;
	}
	/**
	 * 验证ip是否可联通
	 * @param ip
	 * @return
	 */
	public static boolean isPingWorkInfo(String ip){
		boolean iscollect = false;
		String cmdPing = "ping "+ip;
		Runtime run = Runtime.getRuntime();
		Process process;
		try {
			process = run.exec(cmdPing);
			process.waitFor();
			BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), Charset.forName("GBK")));
			String line = null;
			while ((line = br.readLine()) != null){
				if(line.contains("无法访问目标主机")||line.contains("请求超时")){
					iscollect = false;
					break;
				}else if(line.contains("统计信息")||line.contains("字节=")){
					iscollect = true;
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return iscollect;
	}
	/**
	 * 验证端口是否可用
	 * @param ip
	 * @param port
	 * @return
	 */
	public static boolean isUsePort(String ip,Integer port){
		boolean isUse = false;
		String cmdStr = "nc -nvv -w2 "+ip+" "+port;
		Runtime run = Runtime.getRuntime();
		Process process;
		try {
			process = run.exec(cmdStr);
			process.waitFor();
			BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), Charset.forName("GBK")));
			String line = null;
			while ((line = br.readLine()) != null){
				if(line.contains("CONNECT SUCCESS")){ //说明该端口已被其他程序占用，无法使用
					break;
				}else if(line.contains("CONNECT ERROR")){
					isUse = true;
					break;
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return isUse;
	}
	
	
	public static void main(String[] args) throws JSchException, SftpException, IOException {
		/*List<String> out = new ArrayList<>();
		RemoteExecuteLinuxCommandTools.downloadFileBySftp("192.168.168.125","root","root",
				22,"/root/logs.txt","F:/container/",out);*/
		String remoteFilePath = "D:\\lhj\\upload\\uploadFiles\\2025-08-07\\1754534493826_6.json\\stats_1754467453.json";
		remoteFilePath = remoteFilePath.replaceAll("\\\\", "/");
		String fileName =  remoteFilePath.substring(remoteFilePath.lastIndexOf("/")+1,remoteFilePath.length());
		System.out.println(fileName);
	}
	public static String[] deleteArrayNull(String[] string) {
        String[] array = string;
       // 声明一个list
        List<String> list= new ArrayList<>(string.length);
        for (String str : array) {
            list.add(str.trim());
       }
      // 删除空的值
        while (list.remove(null));
        while (list.remove(""));
      // 将list 转换成数组
        String[] list2 = list.toArray(new String[list.size()]);
      // 返回删除空值后的数组
        return list2;
    }

}
